using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Microsoft.Phone.Controls.Primitives
{
	public class PanoramaPanel : Panel
	{
		internal class ItemStop
		{
			public int Index
			{
				get;
				private set;
			}
			public int Position
			{
				get;
				private set;
			}
			public PanoramaItem Item
			{
				get;
				private set;
			}
			public ItemStop(PanoramaItem item, int index, int position)
			{
				this.Item = item;
				this.Index = index;
				this.Position = position;
			}
		}
		private const int SnapThresholdDivisor = 3;
		private Panorama _owner;
		private readonly List<PanoramaItem> _visibleChildren = new List<PanoramaItem>();
		private readonly List<PanoramaPanel.ItemStop> _itemStops = new List<PanoramaPanel.ItemStop>();
		private PanoramaItem _selectedItem;
		internal IList<PanoramaItem> VisibleChildren
		{
			get
			{
				return this._visibleChildren;
			}
		}
		private Panorama Owner
		{
			get
			{
				return this._owner;
			}
			set
			{
				if (this._owner != value)
				{
					if (this._owner != null)
					{
						this._owner.Panel = null;
					}
					this._owner = value;
					if (this._owner != null)
					{
						this._owner.Panel = this;
					}
				}
			}
		}
		public PanoramaPanel()
		{
			PerfLog.BeginLogMarker(PerfMarkerEvents.MPC_PANO_STARTUP, PerfLog.PanoramaPanel);
			base.add_SizeChanged(new SizeChangedEventHandler(this.PanoramaPanel_SizeChanged));
			base.add_Loaded(new RoutedEventHandler(this.PanoramaPanel_Loaded));
			base.add_Unloaded(new RoutedEventHandler(this.PanoramaPanel_UnLoaded));
		}
		private void PanoramaPanel_Loaded(object sender, RoutedEventArgs e)
		{
			base.remove_Loaded(new RoutedEventHandler(this.PanoramaPanel_Loaded));
			PerfLog.EndLogMarker(PerfMarkerEvents.MPC_PANO_STARTUP, PerfLog.PanoramaPanel);
		}
		private void PanoramaPanel_UnLoaded(object sender, RoutedEventArgs e)
		{
			this._owner = null;
		}
		private void PanoramaPanel_SizeChanged(object sender, SizeChangedEventArgs e)
		{
			this.Owner.ItemsWidth = (int)e.get_NewSize().get_Width();
		}
		protected override Size MeasureOverride(Size availableSize)
		{
			PerfLog.BeginLogMarker(PerfMarkerEvents.MPC_PANO_MEASURE, PerfLog.PanoramaPanel);
			if (this._owner == null)
			{
				this.FindOwner();
			}
			int defaultItemIndex = this.GetDefaultItemIndex();
			Size result = new Size(0.0, availableSize.get_Height());
			int adjustedViewportWidth = this.Owner.AdjustedViewportWidth;
			int num = (int)Math.Min(availableSize.get_Height(), (double)this.Owner.ViewportHeight);
			Size size = new Size((double)adjustedViewportWidth, (double)num);
			Size size2 = new Size(double.PositiveInfinity, (double)num);
			int count = base.get_Children().get_Count();
			this._visibleChildren.Clear();
			for (int i = 0; i < count; i++)
			{
				int num2 = (i + defaultItemIndex) % count;
				PanoramaItem panoramaItem = (PanoramaItem)base.get_Children().get_Item(num2);
				if (panoramaItem.get_Visibility() == null)
				{
					this._visibleChildren.Add(panoramaItem);
					panoramaItem.Measure((panoramaItem.Orientation == null) ? size : size2);
					if (panoramaItem.Orientation == null)
					{
						result.set_Width(result.get_Width() + (double)adjustedViewportWidth);
					}
					else
					{
						result.set_Width(result.get_Width() + Math.Max((double)adjustedViewportWidth, panoramaItem.get_DesiredSize().get_Width()));
					}
				}
			}
			PerfLog.EndLogMarker(PerfMarkerEvents.MPC_PANO_MEASURE, PerfLog.PanoramaPanel);
			return result;
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			PerfLog.BeginLogMarker(PerfMarkerEvents.MPC_PANO_ARRANGE, PerfLog.PanoramaPanel);
			this._itemStops.Clear();
			double num = 0.0;
			Rect rect = new Rect(0.0, 0.0, 0.0, finalSize.get_Height());
			for (int i = 0; i < this._visibleChildren.get_Count(); i++)
			{
				PanoramaItem panoramaItem = this._visibleChildren.get_Item(i);
				rect.set_X((double)(panoramaItem.StartPosition = (int)num));
				this._itemStops.Add(new PanoramaPanel.ItemStop(panoramaItem, i, panoramaItem.StartPosition));
				if (panoramaItem.Orientation == null)
				{
					rect.set_Width((double)this.Owner.AdjustedViewportWidth);
				}
				else
				{
					rect.set_Width(Math.Max((double)this.Owner.AdjustedViewportWidth, panoramaItem.get_DesiredSize().get_Width()));
					if (rect.get_Width() > (double)this.Owner.AdjustedViewportWidth)
					{
						this._itemStops.Add(new PanoramaPanel.ItemStop(panoramaItem, i, panoramaItem.StartPosition + (int)rect.get_Width() - this.Owner.AdjustedViewportWidth));
					}
				}
				panoramaItem.ItemWidth = (int)rect.get_Width();
				panoramaItem.Arrange(rect);
				num += rect.get_Width();
			}
			this.Owner.RequestAdjustSelection();
			PerfLog.EndLogMarker(PerfMarkerEvents.MPC_PANO_ARRANGE, PerfLog.PanoramaPanel);
			return finalSize;
		}
		private int GetDefaultItemIndex()
		{
			PanoramaItem defaultItemContainer = this.Owner.GetDefaultItemContainer();
			int num = (defaultItemContainer != null) ? base.get_Children().IndexOf(defaultItemContainer) : 0;
			if (num < 0)
			{
				num = 0;
			}
			return num;
		}
		private void GetItemsInView(int offset, int viewportWidth, out int leftIndex, out int leftInView, out int centerIndex, out int rightIndex, out int rightInView)
		{
			rightInView = -1;
			rightIndex = -1;
			centerIndex = -1;
			leftInView = -1;
			leftIndex = -1;
			int count = this.VisibleChildren.get_Count();
			if (count == 0)
			{
				return;
			}
			for (int i = 0; i < count; i++)
			{
				PanoramaItem panoramaItem = this._visibleChildren.get_Item(i);
				int num = panoramaItem.StartPosition + offset;
				int num2 = num + panoramaItem.ItemWidth - 1;
				if (num <= 0 && num2 >= 0)
				{
					leftIndex = i;
					leftInView = Math.Min(viewportWidth, panoramaItem.ItemWidth + num);
				}
				if (num < viewportWidth && num2 >= viewportWidth)
				{
					rightIndex = i;
					rightInView = Math.Min(viewportWidth, viewportWidth - num);
				}
				if (num > 0 && num2 < viewportWidth)
				{
					centerIndex = i;
				}
				if (i == 0 && leftInView == -1)
				{
					leftInView = num;
				}
				if (i == count - 1 && rightInView == -1)
				{
					rightInView = viewportWidth - num2 - 1;
				}
			}
		}
		internal void GetStops(int offset, int totalWidth, out PanoramaPanel.ItemStop previous, out PanoramaPanel.ItemStop current, out PanoramaPanel.ItemStop next)
		{
			int num3;
			int num2;
			int num = num2 = (num3 = -1);
			PanoramaPanel.ItemStop itemStop;
			previous = (itemStop = null);
			PanoramaPanel.ItemStop itemStop2;
			current = (itemStop2 = itemStop);
			next = itemStop2;
			if (this.VisibleChildren.get_Count() == 0)
			{
				return;
			}
			int num4 = -offset % totalWidth;
			int num5 = 0;
			using (List<PanoramaPanel.ItemStop>.Enumerator enumerator = this._itemStops.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					PanoramaPanel.ItemStop current2 = enumerator.get_Current();
					if (current2.Position < num4)
					{
						num2 = num5;
					}
					else
					{
						if (current2.Position > num4)
						{
							num3 = num5;
							break;
						}
						if (current2.Position == num4)
						{
							num = num5;
						}
					}
					num5++;
				}
			}
			if (num2 == -1)
			{
				num2 = this._itemStops.get_Count() - 1;
			}
			if (num3 == -1)
			{
				num3 = 0;
			}
			previous = this._itemStops.get_Item(num2);
			current = ((num != -1) ? this._itemStops.get_Item(num) : null);
			next = this._itemStops.get_Item(num3);
		}
		internal void GetSnapOffset(int offset, int viewportWidth, int direction, out int snapTo, out int newDirection, out PanoramaItem newSelection, out bool wraparound)
		{
			int num = viewportWidth / 3;
			wraparound = false;
			snapTo = offset;
			newDirection = direction;
			newSelection = this._selectedItem;
			if (this.VisibleChildren.get_Count() == 0)
			{
				return;
			}
			using (List<PanoramaPanel.ItemStop>.Enumerator enumerator = this._itemStops.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					PanoramaPanel.ItemStop current = enumerator.get_Current();
					if (current.Position == -offset)
					{
						newSelection = current.Item;
						return;
					}
				}
			}
			int num2;
			int num3;
			int num4;
			int num5;
			int num6;
			this.GetItemsInView(offset, viewportWidth, out num2, out num3, out num4, out num5, out num6);
			if (num2 != num5 || num2 == -1)
			{
				bool flag = false;
				if (num2 == -1)
				{
					flag = true;
					num2 = this._visibleChildren.get_Count() - 1;
				}
				bool flag2 = false;
				if (num5 == -1)
				{
					flag2 = true;
					num5 = 0;
				}
				int num7;
				if (direction < 0)
				{
					if (num6 > num)
					{
						num7 = PanoramaPanel.GetBestIndex(num4, num5, num2);
						newDirection = -1;
					}
					else
					{
						num7 = PanoramaPanel.GetBestIndex(num2, num4, num5);
						newDirection = 1;
					}
				}
				else
				{
					if (direction > 0)
					{
						if (num3 > num)
						{
							num7 = PanoramaPanel.GetBestIndex(num2, num4, num5);
							newDirection = 1;
						}
						else
						{
							num7 = PanoramaPanel.GetBestIndex(num4, num5, num2);
							newDirection = -1;
						}
					}
					else
					{
						if (num4 != -1)
						{
							num7 = num4;
							newDirection = -1;
						}
						else
						{
							if (num3 > num6)
							{
								num7 = num2;
								newDirection = -1;
							}
							else
							{
								num7 = num5;
								newDirection = 1;
							}
						}
					}
				}
				this._selectedItem = this._visibleChildren.get_Item(num7);
				if (newDirection < 0)
				{
					snapTo = PanoramaPanel.GetLeftAlignedOffset(this._selectedItem, viewportWidth);
				}
				else
				{
					snapTo = PanoramaPanel.GetRightAlignedOffset(this._selectedItem, viewportWidth);
				}
				newSelection = this._selectedItem;
				if ((num7 == num2 && flag) || (num7 == num5 && flag2))
				{
					wraparound = true;
				}
				return;
			}
			newSelection = (this._selectedItem = this._visibleChildren.get_Item(num2));
		}
		private static int GetBestIndex(int n0, int n1, int n2)
		{
			if (n0 >= 0)
			{
				return n0;
			}
			if (n1 >= 0)
			{
				return n1;
			}
			if (n2 < 0)
			{
				throw new InvalidOperationException("No best index.");
			}
			return n2;
		}
		private static int GetLeftAlignedOffset(PanoramaItem movingTo, int viewportWidth)
		{
			return -movingTo.StartPosition;
		}
		private static int GetRightAlignedOffset(PanoramaItem movingTo, int viewportWidth)
		{
			if (movingTo.Orientation != null)
			{
				return -movingTo.ItemWidth + viewportWidth - movingTo.StartPosition - 48;
			}
			return -movingTo.StartPosition;
		}
		private void FindOwner()
		{
			FrameworkElement frameworkElement = this;
			Panorama panorama;
			do
			{
				frameworkElement = (FrameworkElement)VisualTreeHelper.GetParent(frameworkElement);
				panorama = (frameworkElement as Panorama);
			}
			while (frameworkElement != null && panorama == null);
			this.Owner = panorama;
		}
		internal void NotifyDefaultItemChanged()
		{
			base.InvalidateMeasure();
			base.InvalidateArrange();
			base.UpdateLayout();
		}
		internal void ShowLastItemOnLeft()
		{
			this.ResetItemPositions();
			if (this.VisibleChildren.get_Count() > 0)
			{
				PanoramaItem panoramaItem = this.VisibleChildren.get_Item(this.VisibleChildren.get_Count() - 1);
				UIElement arg_42_0 = panoramaItem;
				TranslateTransform translateTransform = new TranslateTransform();
				translateTransform.set_X(-base.get_ActualWidth());
				arg_42_0.set_RenderTransform(translateTransform);
			}
		}
		internal void ShowFirstItemOnRight()
		{
			this.ResetItemPositions();
			if (this.VisibleChildren.get_Count() > 0)
			{
				PanoramaItem panoramaItem = this.VisibleChildren.get_Item(0);
				UIElement arg_35_0 = panoramaItem;
				TranslateTransform translateTransform = new TranslateTransform();
				translateTransform.set_X(base.get_ActualWidth());
				arg_35_0.set_RenderTransform(translateTransform);
			}
		}
		internal void ResetItemPositions()
		{
			using (IEnumerator<PanoramaItem> enumerator = this.VisibleChildren.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					PanoramaItem current = enumerator.get_Current();
					current.set_RenderTransform(null);
				}
			}
		}
	}
}
